`
https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
`

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {number[]} inorder
 * @param {number[]} postorder
 * @return {TreeNode}
 */
var buildTree = function (inorder, postorder) {
  // 存储 inorder 中值到索引的映射
  const valToIndex = {};
  for (let i = 0; i < inorder.length; i++) {
    valToIndex[inorder[i]] = i;
  }

  // 构造二叉树
  return build(
    inorder, 0, inorder.length - 1,
    postorder, 0, postorder.length - 1
  )

  // 给定一个中序遍历数组的范围和一个后序遍历数组的范围
  // 根据这两个范围确定的子数组构建出一颗二叉树，并返回根节点
  function build(inorder, inStart, inEnd, postorder, postStart, postEnd) {
    // 需要构建的数组长度为 0，即不需要构建，返回 null
    if (inStart > inEnd) {
      return null;
    }
    // root 节点对应的值就是后序遍历数组的最后一个元素
    const rootVal = postorder[postEnd];
    // rootVal 在中序遍历数组中的索引
    const index = valToIndex[rootVal];
    // 左子树的节点个数
    const leftSize = index - inStart;

    // 创建根节点
    const root = new TreeNode(rootVal);

    // 递归构造左右子树
    // 这里传递的参数可参考 https://labuladong.online/algo/images/binary-tree-ii/6.jpeg
    root.left = build(
      inorder, inStart, index - 1,
      postorder, postStart, postStart + leftSize - 1
    )
    root.right = build(
      inorder, index + 1, inEnd,
      postorder, postStart + leftSize, postEnd - 1
    )

    return root;
  }
};